// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: daniel

#include <memory>

#include "coin/proto/coin_telemetry.pb.h"
#include "coin2/exchange/base/log/latency_recorder.h"
#include "coin2/exchange/base/order/order.h"

namespace coin2::exchange::base::strategy_util {

class LatencyRecorderGlobal {
 public:
  static void SetLatencyProfileMark(
      LatencyRecorder* latency_recorder,
      const coin::proto::AccountRequestProto& acc_request,
      std::string_view tag,
      int64_t point_timestamp,
      int64_t* context_id,
      bool is_end_mark) {
    if (!latency_recorder) {
      LOG_FIRST_N(ERROR, 10) << "latency recorder is not set";
      return;
    }
    if (0 == *context_id) {  // create new life of signal
      latency_recorder->Begin(coin::proto::LatencyProto::ORDER_LATENCY);
      *context_id = latency_recorder->GetCurrentContextId();
    }
    latency_recorder->SetProtoAndTime(
        *context_id,
        coin::proto::LifeOfSignal::LATENCY_PROFILE_MARK,
        point_timestamp == 0 ? GetCurrentTimestamp() : point_timestamp,
        acc_request,
        tag.data());
    if (is_end_mark) {
      latency_recorder->End(*context_id);
    }
  }

  static void SetLatencyProfileMark(
      const coin::proto::AccountRequestProto& acc_request,
      std::string_view tag,
      int64_t point_timestamp,
      int64_t* context_id,
      bool is_end_mark) {
    SetLatencyProfileMark(Get(), acc_request, tag, point_timestamp, context_id, is_end_mark);
  }

  static void Set(LatencyRecorder* latency_recorder) { g_latency_recorder = latency_recorder; }
  static auto Get() -> LatencyRecorder* { return g_latency_recorder; }

 protected:
  LatencyRecorderGlobal() = delete;
  ~LatencyRecorderGlobal() = delete;

 private:
  inline static LatencyRecorder* g_latency_recorder = nullptr;
};

}  // namespace coin2::exchange::base::strategy_util
